#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <math.h>
#include <fcntl.h>
#include <unistd.h>
#include <linux/ioctl.h>
#include <sys/ioctl.h>
#include <system/imp_alloc.h>
#include "ncu.h"
#include "ncureg.h"
#include "common.h"
#include "ncuopt.h"
#ifdef DMALLOC
#include <imp/dmalloc.h>
#endif
#define NCU_DEV "/dev/ncu0"
#define PP_DEV "/dev/pp0"
ncu_info ncuinfo;
uint32_t ncu_inited = 0;


int ncu_fun_ctrl(uint32_t funcs)
{
	uint32_t reg = 0;
	reg = ncu_reg_read(NCU_FUN_CNTRL);
	//do not touch bit 0xff
	reg = (funcs&(~0xff))|(reg&0xff);
    ncu_reg_write(NCU_FUN_CNTRL, reg);
    printf("funcs: 0x%x\n",funcs);
    return 0;
}

int ncu_in_mode(uint32_t mode)
{
	uint32_t reg = 0;
	reg = ncu_reg_read(NCU_FUN_CNTRL);
	if (0 == mode) {
		reg &= (~(0x1<<4));
	} else {
		reg |= (0x1<<4);
	}
    ncu_reg_write(NCU_FUN_CNTRL, reg);
    return 0;
}

int ncu_out_mode(uint32_t mode)
{
	uint32_t reg = 0;
	reg = ncu_reg_read(NCU_FUN_CNTRL);
	if (0 == mode) {
		reg &= (~(0x1<<5));
	} else {
		reg |= (0x1<<5);
	}
    ncu_reg_write(NCU_FUN_CNTRL, reg);
    return 0;
}

int ncu_set_src_dst_stride(uint32_t width)
{
    ncu_reg_write(Y_CUR_STRIDE, width);
    ncu_reg_write(UV_CUR_STRIDE, width);
    ncu_reg_write(Y_REF_BUF0_STRIDE, width);
    ncu_reg_write(UV_REF_BUF0_STRIDE, width);
    ncu_reg_write(Y_REF_BUF1_STRIDE, width);
    ncu_reg_write(UV_REF_BUF1_STRIDE, width);

    return 0;
}

int pp_set_stride(uint32_t width)
{
    ncu_reg_write(NCU_PP_Y_BUF0_STRIDE, width);
    ncu_reg_write(NCU_PP_Y_BUF1_STRIDE, width);
    ncu_reg_write(NCU_PP_UV_BUF0_STRIDE, width);
    ncu_reg_write(NCU_PP_UV_BUF1_STRIDE, width);
    return 0;
}

int pp_set_sta_stride(uint32_t y)
{
    ncu_reg_write(NCU_PP_STA_BUF0_STRIDE, y);
    ncu_reg_write(NCU_PP_STA_BUF1_STRIDE, y);
	return 0;
}

int ncu_set_sta_stride(uint32_t y, uint32_t u, uint32_t v)
{
    ncu_reg_write(Y_STA_STRIDE, y);
    ncu_reg_write(U_STA_STRIDE, u);
    ncu_reg_write(V_STA_STRIDE, v);
    ncu_reg_write(Y_STA_FRM_STRIDE, 0);
    ncu_reg_write(U_STA_FRM_STRIDE, 0);
    ncu_reg_write(V_STA_FRM_STRIDE, 0);
	return 0;
}

int ncu_set_psn_stride(uint32_t y, uint32_t uv)
{
    ncu_reg_write(Y_PSN_STRIDE, y);
    ncu_reg_write(U_PSN_STRIDE, uv);
    ncu_reg_write(V_PSN_STRIDE, uv);
    ncu_reg_write(Y_PSN_FRM_STRIDE, 0);
    ncu_reg_write(U_PSN_FRM_STRIDE, 0);
    ncu_reg_write(V_PSN_FRM_STRIDE, 0);

	return 0;
}

int ncu_set_ref0_buffer(uint32_t yaddr, uint32_t uvaddr)
{
    ncu_reg_write(Y_REF_BUF0_ADDR, yaddr);
    ncu_reg_write(UV_REF_BUF0_ADDR, uvaddr);
	return 0;
}

int ncu_set_ref1_buffer(uint32_t yaddr, uint32_t uvaddr)
{
    ncu_reg_write(Y_REF_BUF1_ADDR, yaddr);
    ncu_reg_write(UV_REF_BUF1_ADDR, uvaddr);
	return 0;
}

int ncu_set_cur_buffer(uint32_t yaddr, uint32_t uvaddr)
{
    ncu_reg_write(Y_CUR_ADDR, yaddr);
    ncu_reg_write(UV_CUR_ADDR, uvaddr);
	return 0;
}

int pp_set_buf0_buffer(uint32_t yaddr, uint32_t uvaddr)
{
    ncu_reg_write(NCU_PP_Y_BUF0_ADDR, yaddr);
    ncu_reg_write(NCU_PP_UV_BUF0_ADDR, uvaddr);
	return 0;
}

int pp_set_buf1_buffer(uint32_t yaddr, uint32_t uvaddr)
{
    ncu_reg_write(NCU_PP_Y_BUF1_ADDR, yaddr);
    ncu_reg_write(NCU_PP_UV_BUF1_ADDR, uvaddr);
	return 0;
}

int pp_set_sta_buf0(uint32_t yaddr)
{
    ncu_reg_write(NCU_PP_STA_BUF0_ADDR, yaddr);
	return 0;
}

int pp_set_sta_buf1(uint32_t yaddr)
{
    ncu_reg_write(NCU_PP_STA_BUF1_ADDR, yaddr);
	return 0;
}

int pp_interrupt_en(uint32_t en)
{
    ncu_reg_write(NCU_PP_INT_CNTRL, en?1:0);
	return 0;
}

int ncu_interrupt_en(uint32_t en)
{
    ncu_reg_write(NCU_INT_CNTRL, en?1:0);
	return 0;
}

int ncu_interrupt_clear()
{
	uint32_t reg = 0;
	reg = ncu_reg_read(NCU_INT_CNTRL);
    ncu_reg_write(NCU_INT_CNTRL, (reg|0x2));
	return 0;
}

int pp_interrupt_clear()
{
	uint32_t reg = 0;
	reg = ncu_reg_read(NCU_PP_INT_CNTRL);
    ncu_reg_write(NCU_PP_INT_CNTRL, (reg|0x2));
	return 0;
}

int ncu_set_sta_buffer(uint32_t yaddr, uint32_t uaddr, uint32_t vaddr)
{
    ncu_reg_write(Y_STA_ADDR, yaddr);
    ncu_reg_write(U_STA_ADDR, uaddr);
    ncu_reg_write(V_STA_ADDR, vaddr);
	return 0;
}

int ncu_set_psn_buffer(uint32_t yaddr, uint32_t uaddr, uint32_t vaddr)
{
    ncu_reg_write(Y_PSN_ADDR, yaddr);
    //    ncu_reg_write(Y_PSN_ADDR, 0);
    ncu_reg_write(U_PSN_ADDR, uaddr);
    ncu_reg_write(V_PSN_ADDR, vaddr);
	return 0;
}

int ncu_set_frame_size(uint32_t w, uint32_t h)
{
    //ncu_reg_write(NCU_FRAME_SIZE, (w)|(h<<16));
    ncuinfo.src_attr.frm_w = w;
    ncuinfo.src_attr.frm_h = h;
    return 0;
}

int pp_set_frame_size(uint32_t w, uint32_t h)
{
    ncu_reg_write(NCU_PP_FRM_SIZE, (w)|(h<<16));
    return 0;
}


int ncu_open(const char *dev_name)
{
	if(NULL == dev_name) {
		printf("error:(%s,%d),dev_name is null.\n",__func__,__LINE__);
		return -1;
	}
	int fd = open(dev_name, O_RDWR);
	if (fd < 0) {
		printf("error:(%s,%d),open ncu faild\n",__func__,__LINE__);
		return -1;
	} else {
		printf("info:(%s,%d),open ncu Ok.\n",__func__,__LINE__);
		return fd;
	}
}

int ncu_frame_finish(int fd)
{
	int ret = -1;
	ret = ioctl(fd, IOCTL_NCU_WAIT, 1);
	if(ret < 0) {
		printf("error:(%s,%d),ioctl failed.%s\n",__func__,__LINE__, strerror(errno));
		return -1;
	}
	return 0;
}
int pp_frame_finish(int fd)
{
	int ret = -1;
	ret = ioctl(fd, IOCTL_PP_WAIT, 1);
	if(ret < 0) {
		printf("error:(%s,%d),ioctl failed.\n",__func__,__LINE__);
		return -1;
	}

	return 0;
}

int ncu_init()
{
	int ret = -1;
#ifdef NCU_POLLING
	uint32_t loopcnt = 0;
	uint32_t end = 0;
	uint32_t reg;
#endif
	int fd = 0;
	if (1 == ncu_inited) {
        printf("warn: ncu already inited\n");
		return 0;
	}

    memset(&ncuinfo, 0, sizeof(ncuinfo));
	//ncu_map();
	fd = ncu_open(NCU_DEV);
	if(fd < 0) {
        printf("err: ncu fd %d\n", fd);
	}
	else
	  ncuinfo.fd = fd;

#ifdef NCU_POLLING
	ncu_interrupt_en(0);
#else
	ncu_interrupt_en(1);
#endif
    ncu_reg_write(NCU_CLK_CNT, 0x1);
    ncu_stop();
#ifdef NCU_POLLING
	loopcnt = 0;
	end = 0;
	while (0 == end) {
		end = ncu_frame_end();
		if (0 != end) {
			ncu_interrupt_clear();
		}
		loopcnt++;
		assert(loopcnt < 50);
		usleep(100*1000);
	}
#else
	ncu_info *pncuinfo = (ncu_info*)ncu_get_info();
	ret = ncu_frame_finish(pncuinfo->fd);
	if(ret < 0) {
		printf("error:(%s,%d),failed\n",__func__,__LINE__);
		return -1;
	}
#endif
    ncu_reset();
#ifdef NCU_POLLING
	reg = ncu_reg_read(NCU_INT_CNTRL);
	ncu_reg_write(NCU_INT_CNTRL, reg|0x2);
#endif
	ncu_inited = 1;

    return 0;
}

int ncu_deinit()
{
	//ncu_umap();
	close(ncuinfo.fd);
	ncu_inited = 0;
    return 0;
}

int pp_stop();
int pp_reset();
int pp_init()
{
	int ret = -1;
#ifdef PP_POLLING
	uint32_t loopcnt = 0;
	uint32_t end = 0;
#endif
	uint32_t reg = 0;

	int fd = ncu_open(PP_DEV);
	if(fd < 0)
		return -1;
	else
	  ncuinfo.fd_pp = fd;

    //ncu_map();
#ifdef PP_POLLING
#else
	pp_interrupt_en(1);
#endif
	ncu_info *pncuinfo = (ncu_info*)ncu_get_info();
    pp_stop();
	// do not stop here
#ifdef PP_POLLING
	//pooling
	loopcnt = 0;
	end = 0;
	while (0 == end) {
		end = pp_frame_end();
		if (0 != end) {
			pp_interrupt_clear();
		}
		//pp_reg_ready();
		loopcnt++;
		assert(loopcnt < 500);
		usleep(100*1000);
	}
#else
	ret = pp_frame_finish(pncuinfo->fd_pp);
	if( ret < 0) {
		printf("error:(%s,%d),failed\n",__func__,__LINE__);
		return -1;
	}
#endif

#if 0
	while (0 == end) {
		end = pp_frame_end();
		loopcnt++;
		assert(loopcnt < 30);
		usleep(100*1000);
	}
#endif
	reg = ncu_reg_read(NCU_PP_INT_CNTRL);
	ncu_reg_write(NCU_PP_INT_CNTRL, reg|0x2);
    pp_reset();
	ncu_reg_write(NCU_PP_ADDR_CNTRL, 0x110);

    return 0;
}

int pp_ready()
{
	/* disable pingpang */
	ncu_reg_write(NCU_PP_ADDR_CNTRL, 0x111);
    return 0;
}

int pp_reg_ready()
{
	uint32_t reg = 0;
	reg = ncu_reg_read(NCU_PP_SREG_CNTRL);
	ncu_reg_write(NCU_PP_SREG_CNTRL, reg|0x1);
    return 0;
}

int pp_func_en(uint32_t en)
{
	ncu_reg_write(NCU_PP_FUN_CNTRL, (en?1:0));
    return 0;
}


uint32_t ncu_get_info()
{
    uint32_t p = (uint32_t)&ncuinfo;
    return p;
}

int ncu_config_ready()
{
    ncu_reg_write(NCU_SREG_CNTRL,0x1);
	return 0;
}

int ncu_get_clkcnt()
{
    uint32_t cnt;
    cnt = ncu_reg_read(NCU_CLK_CNT);
    return cnt;
}

int ncu_reset()
{
    ncu_reg_write(NCU_RESET, 0x0);
    return 0;
}

int pp_reset()
{
    ncu_reg_write(NCU_PP_RESET, 0x0);
    return 0;
}

int ncu_start()
{
    ncu_reg_write(NCU_START, 0x1);
    return 0;
}

int ncu_stop()
{
    ncu_reg_write(NCU_STOP, 0x1);
    return 0;
}

int pp_stop()
{
    ncu_reg_write(NCU_PP_STOP, 0x1);
    return 0;
}

int ncu_first_frame()
{
    ncu_reg_write(NCU_START, 1<<1);
    return 0;
}

int pp_first_frame()
{
    ncu_reg_write(NCU_PP_FST_FRM, 1);
    return 0;
}

uint32_t ncu_frame_end()
{
    uint32_t reg;
#if 1
    reg = ((ncu_reg_read(NCU_INT_CNTRL)&0x10) >> 4);
#else
	//do not use it
    reg = ((ncu_reg_read(NCU_STOP)&0x2) >> 1);
#endif
    return reg;
}

uint32_t pp_frame_end()
{
    uint32_t reg;
#if 1
    reg = ((ncu_reg_read(NCU_PP_INT_CNTRL)&0x10) >> 4);
#else
	//do not use it
    reg = ((ncu_reg_read(NCU_PP_STOP)&0x2) >> 1);
#endif
    return reg;
}

uint32_t pp_get_frmnum()
{
    uint32_t frmnum;
    ncu_reg_write(NCU_DEBUG_SEL, 0x15);
    frmnum = ncu_reg_read(NCU_DEBUG_VAL);
    ncu_reg_write(NCU_DEBUG_SEL, 0x0);
    return frmnum;
}

int ncu_set_cut_value(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(NCU_CUT_VALUE,NcuFilter->cut_value);
    return 0;
}

int ncu_set_yFs(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(Y_FS_AVE_PAR               ,NcuFilter->yFs.ave);
    ncu_reg_write(Y_FS_SIGMA_CORR_AD_X_PAR   ,NcuFilter->yFs.sgm_corr_x);
    ncu_reg_write(Y_FS_SIGMA_CORR_AD_Y_PAR   ,NcuFilter->yFs.sgm_corr_y);
    ncu_reg_write(Y_FS_SIGMA_CORR_AD_S_PAR   ,NcuFilter->yFs.sgm_corr_s);
    ncu_reg_write(Y_FS_SIGMA_PFR_AD_X_PAR    ,NcuFilter->yFs.sgm_pfr_x);
    ncu_reg_write(Y_FS_SIGMA_PFR_AD_Y_PAR    ,NcuFilter->yFs.sgm_pfr_y);
    ncu_reg_write(Y_FS_SIGMA_PFR_AD_S_PAR    ,NcuFilter->yFs.sgm_pfr_s);
    ncu_reg_write(Y_FS_PFR_DIFF_PAR0         ,NcuFilter->yFs.pfr_diff0);
    ncu_reg_write(Y_FS_PFR_DIFF_PAR1         ,NcuFilter->yFs.pfr_diff1);
    ncu_reg_write(Y_FS_FLUCT_HG_DIFF_PAR     ,NcuFilter->yFs.fluct_hg_diff);
    ncu_reg_write(Y_FS_FLUCT_BR_DIFF_PAR     ,NcuFilter->yFs.fluct_uhg_br_diff);
    ncu_reg_write(Y_FS_FLUCT_DK_DIFF_PAR     ,NcuFilter->yFs.fluct_uhg_dk_diff);
    ncu_reg_write(Y_FS_PXL_DIFF_THRES        ,NcuFilter->yFs.pxl_diff_thres);
    return 0;
}

int ncu_set_ySe(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(Y_SE_AVE_PAR          ,NcuFilter->ySe.ave             );
    ncu_reg_write(Y_SE_SIGMA_BDV_X_PAR0 ,NcuFilter->ySe.sgm_bdv_x_0     );
    ncu_reg_write(Y_SE_SIGMA_BDV_X_PAR1 ,NcuFilter->ySe.sgm_bdv_x_1     );
    ncu_reg_write(Y_SE_SIGMA_BDV_Y_PAR0 ,NcuFilter->ySe.sgm_bdv_y_0     );
    ncu_reg_write(Y_SE_SIGMA_BDV_Y_PAR1 ,NcuFilter->ySe.sgm_bdv_y_1     );
    ncu_reg_write(Y_SE_SIGMA_BDV_S_PAR0 ,NcuFilter->ySe.sgm_bdv_s_0     );
    ncu_reg_write(Y_SE_SIGMA_BDV_S_PAR1 ,NcuFilter->ySe.sgm_bdv_s_1     );
    ncu_reg_write(Y_SE_BDV_ADJ_PAR0     ,NcuFilter->ySe.sgm_bdv_adj_0   );
    ncu_reg_write(Y_SE_BDV_ADJ_PAR1     ,NcuFilter->ySe.sgm_bdv_adj_1   );
    ncu_reg_write(Y_SE_BDV_ADJ_PAR2     ,NcuFilter->ySe.sgm_bdv_adj_2   );
    ncu_reg_write(Y_SE_BDV_ADJ_PAR3     ,NcuFilter->ySe.sgm_bdv_adj_3   );
    ncu_reg_write(Y_SE_DIFF_THRES       ,NcuFilter->ySe.pxl_diff_thres  );
    ncu_reg_write(Y_SE_STATIS_PAR       ,NcuFilter->ySe.statis_par      );
    ncu_reg_write(Y_SE_REF_WEI          ,NcuFilter->ySe.ref_wei         );
    ncu_reg_write(Y_SE_CORNER_PAR       ,NcuFilter->ySe.coner_par       );
    return 0;
}

int ncu_set_uvFs(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(UV_FS_AVE_PAR           ,NcuFilter->uvFs.ave            );
    ncu_reg_write(UV_FS_CORR_SIGMA_X      ,NcuFilter->uvFs.sgm_corr_x     );
    ncu_reg_write(UV_FS_CORR_SIGMA_Y      ,NcuFilter->uvFs.sgm_corr_y     );
    ncu_reg_write(UV_FS_CORR_SIGMA_S      ,NcuFilter->uvFs.sgm_corr_s     );
    ncu_reg_write(UV_FS_PFR_SIGMA_X       ,NcuFilter->uvFs.sgm_pfr_x      );
    ncu_reg_write(UV_FS_PFR_SIGMA_Y       ,NcuFilter->uvFs.sgm_pfr_y      );
    ncu_reg_write(UV_FS_PFR_SIGMA_S       ,NcuFilter->uvFs.sgm_pfr_s      );
    ncu_reg_write(UV_FS_PFR_DIFF_PAR_0    ,NcuFilter->uvFs.pfr_diff0      );
    ncu_reg_write(UV_FS_PFR_DIFF_PAR_1    ,NcuFilter->uvFs.pfr_diff1      );
    ncu_reg_write(UV_FS_HG_FLUCT_PAR      ,NcuFilter->uvFs.fluct_hg_diff  );
    ncu_reg_write(UV_FS_UHG_BR_FLUCT_PAR  ,NcuFilter->uvFs.fluct_uhg_br_diff  );
    ncu_reg_write(UV_FS_UHG_DK_FLUCT_PAR  ,NcuFilter->uvFs.fluct_uhg_dk_diff  );
    return 0;
}

int ncu_set_uvSe(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(UV_SE_CON_PAR            ,NcuFilter->uvSe.ave             );
    ncu_reg_write(UV_SE_PIX_LINE_THRES     ,NcuFilter->uvSe.pxl_diff_thres  );
    ncu_reg_write(UV_SE_BDV_SIGMA_X_0      ,NcuFilter->uvSe.sgm_bdv_x_0     );
    ncu_reg_write(UV_SE_BDV_SIGMA_X_1      ,NcuFilter->uvSe.sgm_bdv_x_1     );
    ncu_reg_write(UV_SE_BDV_SIGMA_Y_0      ,NcuFilter->uvSe.sgm_bdv_y_0     );
    ncu_reg_write(UV_SE_BDV_SIGMA_Y_1      ,NcuFilter->uvSe.sgm_bdv_y_1     );
    ncu_reg_write(UV_SE_BDV_SIGMA_S_0      ,NcuFilter->uvSe.sgm_bdv_s_0     );
    ncu_reg_write(UV_SE_BDV_SIGMA_S_1      ,NcuFilter->uvSe.sgm_bdv_s_1     );
    ncu_reg_write(UV_SE_BDV_ADJ_0          ,NcuFilter->uvSe.sgm_bdv_adj_0   );
    ncu_reg_write(UV_SE_BDV_ADJ_1          ,NcuFilter->uvSe.sgm_bdv_adj_1   );
    ncu_reg_write(UV_SE_BDV_ADJ_2          ,NcuFilter->uvSe.sgm_bdv_adj_2   );
    ncu_reg_write(UV_SE_BDV_ADJ_3          ,NcuFilter->uvSe.sgm_bdv_adj_3  );
    ncu_reg_write(UV_SE_CORNER_PAR         ,NcuFilter->uvSe.coner_par       );

    return 0;
}

//set ncu y fusion filter
int ncu_set_yFusion(ncu_filter_para *NcuFilter)
{

    ncu_reg_write(Y_FUSION_AVE_PAR           ,NcuFilter->yFusion.ave             );
    ncu_reg_write(Y_S_FUSION_SGM_EDGE_X_PAR0 ,NcuFilter->yFusion.y_s.sgm_edge_x_0);
    ncu_reg_write(Y_S_FUSION_SGM_EDGE_X_PAR1 ,NcuFilter->yFusion.y_s.sgm_edge_x_1);
    ncu_reg_write(Y_S_FUSION_SGM_EDGE_Y_PAR0 ,NcuFilter->yFusion.y_s.sgm_edge_y_0);
    ncu_reg_write(Y_S_FUSION_SGM_EDGE_Y_PAR1 ,NcuFilter->yFusion.y_s.sgm_edge_y_1);
    ncu_reg_write(Y_S_FUSION_SGM_EDGE_S_PAR0 ,NcuFilter->yFusion.y_s.sgm_edge_s_0);
    ncu_reg_write(Y_S_FUSION_SGM_EDGE_S_PAR1 ,NcuFilter->yFusion.y_s.sgm_edge_s_1);
    ncu_reg_write(Y_S_FUSION_SGM_PFR_X_PAR0  ,NcuFilter->yFusion.y_s.sgm_pfr_x_0 );
    ncu_reg_write(Y_S_FUSION_SGM_PFR_X_PAR1  ,NcuFilter->yFusion.y_s.sgm_pfr_x_1 );
    ncu_reg_write(Y_S_FUSION_SGM_PFR_Y_PAR0  ,NcuFilter->yFusion.y_s.sgm_pfr_y_0 );
    ncu_reg_write(Y_S_FUSION_SGM_PFR_Y_PAR1  ,NcuFilter->yFusion.y_s.sgm_pfr_y_1 );
    ncu_reg_write(Y_S_FUSION_SGM_PFR_S_PAR0  ,NcuFilter->yFusion.y_s.sgm_pfr_s_0 );
    ncu_reg_write(Y_S_FUSION_SGM_PFR_S_PAR1  ,NcuFilter->yFusion.y_s.sgm_pfr_s_1 );
    ncu_reg_write(Y_S_FUSION_ORG_SUP_THRES   ,NcuFilter->yFusion.y_s.org_sup_thres  );
    ncu_reg_write(Y_M_FUSION_SGM_EDGE_X_PAR0 ,NcuFilter->yFusion.y_m.sgm_edge_x_0);
    ncu_reg_write(Y_M_FUSION_SGM_EDGE_X_PAR1 ,NcuFilter->yFusion.y_m.sgm_edge_x_1);
    ncu_reg_write(Y_M_FUSION_SGM_EDGE_Y_PAR0 ,NcuFilter->yFusion.y_m.sgm_edge_y_0);
    ncu_reg_write(Y_M_FUSION_SGM_EDGE_Y_PAR1 ,NcuFilter->yFusion.y_m.sgm_edge_y_1);
    ncu_reg_write(Y_M_FUSION_SGM_EDGE_S_PAR0 ,NcuFilter->yFusion.y_m.sgm_edge_s_0);
    ncu_reg_write(Y_M_FUSION_SGM_EDGE_S_PAR1 ,NcuFilter->yFusion.y_m.sgm_edge_s_1);
    ncu_reg_write(Y_M_FUSION_SGM_PFR_X_PAR0  ,NcuFilter->yFusion.y_m.sgm_pfr_x_0 );
    ncu_reg_write(Y_M_FUSION_SGM_PFR_X_PAR1  ,NcuFilter->yFusion.y_m.sgm_pfr_x_1 );
    ncu_reg_write(Y_M_FUSION_SGM_PFR_Y_PAR0  ,NcuFilter->yFusion.y_m.sgm_pfr_y_0 );
    ncu_reg_write(Y_M_FUSION_SGM_PFR_Y_PAR1  ,NcuFilter->yFusion.y_m.sgm_pfr_y_1 );
    ncu_reg_write(Y_M_FUSION_SGM_PFR_S_PAR0  ,NcuFilter->yFusion.y_m.sgm_pfr_s_0 );
    ncu_reg_write(Y_M_FUSION_SGM_PFR_S_PAR1  ,NcuFilter->yFusion.y_m.sgm_pfr_s_1 );
    ncu_reg_write(Y_M_FUSION_ORG_SUP_THRES   ,NcuFilter->yFusion.y_m.org_sup_thres   );

    return 0;

}

int ncu_set_uvFusion(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(UV_FUSION_MV_JUDGE_THRES  ,NcuFilter->uvFusion.mv_judge_thres      );
    ncu_reg_write(UV_FUSION_S_EDGE_SIGMA_X  ,NcuFilter->uvFusion.uv_s.sgm_edge_x_0     );
    ncu_reg_write(UV_FUSION_S_EDGE_SIGMA_Y  ,NcuFilter->uvFusion.uv_s.sgm_edge_y_0     );
    ncu_reg_write(UV_FUSION_S_EDGE_SIGMA_S  ,NcuFilter->uvFusion.uv_s.sgm_edge_s_0     );
    ncu_reg_write(UV_FUSION_S_PFR_SIGMA_X   ,NcuFilter->uvFusion.uv_s.sgm_pfr_x_0     );
    ncu_reg_write(UV_FUSION_S_PFR_SIGMA_Y   ,NcuFilter->uvFusion.uv_s.sgm_pfr_y_0     );
    ncu_reg_write(UV_FUSION_S_PFR_SIGMA_S   ,NcuFilter->uvFusion.uv_s.sgm_pfr_s_0     );
    ncu_reg_write(UV_FUSION_S_BLUR_PAR      ,NcuFilter->uvFusion.uv_s.blur_par        );
    ncu_reg_write(UV_FUSION_S_LUM_PAR       ,NcuFilter->uvFusion.uv_s.lum_par         );
    ncu_reg_write(UV_FUSION_M_EDGE_SIGMA_X  ,NcuFilter->uvFusion.uv_m.sgm_edge_x_0   );
    ncu_reg_write(UV_FUSION_M_EDGE_SIGMA_Y  ,NcuFilter->uvFusion.uv_m.sgm_edge_y_0   );
    ncu_reg_write(UV_FUSION_M_EDGE_SIGMA_S  ,NcuFilter->uvFusion.uv_m.sgm_edge_s_0   );
    ncu_reg_write(UV_FUSION_M_PFR_SIGMA_X   ,NcuFilter->uvFusion.uv_m.sgm_pfr_x_0    );
    ncu_reg_write(UV_FUSION_M_PFR_SIGMA_Y   ,NcuFilter->uvFusion.uv_m.sgm_pfr_y_0    );
    ncu_reg_write(UV_FUSION_M_PFR_SIGMA_S   ,NcuFilter->uvFusion.uv_m.sgm_pfr_s_0    );
    ncu_reg_write(UV_FUSION_M_BLUR_PAR      ,NcuFilter->uvFusion.uv_m.blur_par       );
    ncu_reg_write(UV_FUSION_M_LUM_PAR       ,NcuFilter->uvFusion.uv_m.lum_par        );
    return 0;
}

int ncu_set_y_sta_psn(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(YUV_STA_FRM_MAX_NUM   ,NcuFilter->psn_max_num     );
    ncu_reg_write(YUV_PSN_FRM_MAX_NUM   ,NcuFilter->sta_max_num     );
    ncu_reg_write(Y_PSN_PAR_0           ,NcuFilter->yPsnSta.psn_par0    );
    ncu_reg_write(Y_PSN_PAR_1           ,NcuFilter->yPsnSta.psn_par1    );
    ncu_reg_write(Y_STA_AVE_PAR         ,NcuFilter->yPsnSta.sta_ave            );
    ncu_reg_write(Y_STA_SIZE_PAR        ,NcuFilter->yPsnSta.sta_size           );
    ncu_reg_write(Y_STA_SIZE_INCR_PAR    ,NcuFilter->yPsnSta.sta_size_incr );
    //ncu_reg_write(Y_STA_SIZE_NUM_PAR     ,NcuFilter->yPsnSta.sta_size_num );
    ncu_reg_write(Y_STA_MV_BLK_ADJ      ,NcuFilter->yPsnSta.sta_mv_blk_adj    );
    ncu_reg_write(Y_STA_DIFF_THRES      ,NcuFilter->yPsnSta.sta_diff_thres     );
    ncu_reg_write(Y_STA_MV_NUM_THRES    ,NcuFilter->yPsnSta.sta_mv_num_thres   );
    ncu_reg_write(Y_LUM_AREA_PAR        ,NcuFilter->yPsnSta.sta_lum_area       );
    return 0;
}

int ncu_set_ncu_uv_sta_psn(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(UV_PSN_PAR_0        ,NcuFilter->uvPsnSta.psn_par0     );
    ncu_reg_write(UV_PSN_PAR_1        ,NcuFilter->uvPsnSta.psn_par1     );
    ncu_reg_write(UV_STA_BLK_SIZE     ,NcuFilter->uvPsnSta.sta_size          );
    ncu_reg_write(UV_STA_BLK_SIZE_INCR    ,NcuFilter->uvPsnSta.sta_size_incr );
    //ncu_reg_write(UV_STA_BLK_SIZE_NUM     ,NcuFilter->uvPsnSta.sta_size_num );
    ncu_reg_write(UV_STA_BLK_ADJ      ,NcuFilter->uvPsnSta.sta_mv_blk_adj     );
    ncu_reg_write(UV_STA_DIFF_THRES   ,NcuFilter->uvPsnSta.sta_diff_thres      );
    ncu_reg_write(UV_STA_NUM_THRES    ,NcuFilter->uvPsnSta.sta_mv_num_thres    );
    ncu_reg_write(UV_FALSE_COLOR_PAR  ,NcuFilter->uvPsnSta.sta_fals_color_par     );
    return 0;
}

int ncu_set_sta_size(uint32_t frm_w, uint32_t frm_h, uint32_t y_blk_w, uint32_t y_blk_h, uint32_t uv_blk_w, uint32_t uv_blk_h)
{
	uint32_t stasize = 0;
	uint32_t w = 0;
	uint32_t wnum = 0;
	uint32_t h = 0;
	uint32_t hnum = 0;
	wnum = y_blk_w;
	hnum = y_blk_h;
	w = DIV_ROUND_UP(frm_w, 16*(wnum));
	h = DIV_ROUND_UP(frm_h, 16*(hnum));
	stasize = ((w&0xff)<<16)|
		(h&0x3ff);
    ncu_reg_write(Y_STA_SIZE_NUM_PAR, stasize);
    ncu_reg_write(Y_STA_SIZE_PAR, ((wnum<<16)|hnum));
	wnum = uv_blk_w;
	hnum = uv_blk_h;
	w = DIV_ROUND_UP(frm_w, 2*16*(wnum));
	h = DIV_ROUND_UP(frm_h, 2*16*(hnum));
	stasize = ((w&0xff)<<16)|
		(h&0xff);
    ncu_reg_write(UV_STA_BLK_SIZE_NUM, stasize);
    ncu_reg_write(UV_STA_BLK_SIZE, ((wnum<<16)|hnum));
	return 0;
}

int pp_set_sta_size(uint32_t frm_w, uint32_t frm_h, uint32_t y_blk_w, uint32_t y_blk_h)
{
	uint32_t reg = 0;
	uint32_t w = 0;
	uint32_t wnum = 0;
	uint32_t h = 0;
	uint32_t hnum = 0;
	wnum = y_blk_w;
	hnum = y_blk_h;
	w = DIV_ROUND_UP(frm_w, 16*(wnum));
	h = DIV_ROUND_UP(frm_h, 16*(hnum));
	reg = ((w&0xff)<<24)|(wnum<<16)|((h&0xff)<<8)|(hnum);
    ncu_reg_write(NCU_PP_STA_BLK_SIZE, reg);
	return 0;
}

int ncu_set_stage2(ncu_filter_para *NcuFilter)
{
    ncu_reg_write(Y_ST2_SGM_P_X_PAR      ,NcuFilter->ySt2.sgm_p_x   );
    ncu_reg_write(Y_ST2_SGM_P_Y_PAR      ,NcuFilter->ySt2.sgm_p_y   );
    ncu_reg_write(Y_ST2_SGM_P_S_PAR      ,NcuFilter->ySt2.sgm_p_s   );
    ncu_reg_write(Y_ST2_GAUS_SGM_PAR     ,NcuFilter->ySt2.gaus_sgm  );

    return 0;
}

int ncu_get_value(ncu_filter_para *NcuFilter)
{
    return 0;
}

int ncu_set_filter_allpara(ncu_filter_para *filter_para)
{
    ncu_set_cut_value(filter_para);
    ncu_set_yFs(filter_para);
    ncu_set_ySe(filter_para);
    ncu_set_yFusion(filter_para);
    ncu_set_y_sta_psn(filter_para);
    ncu_set_uvFs(filter_para);
    ncu_set_uvSe(filter_para);
    ncu_set_uvFusion(filter_para);
    ncu_set_ncu_uv_sta_psn(filter_para);
    ncu_set_stage2(filter_para);
    return 0;
}

int ncu_all_buf_config(ncu_info *info, uint32_t isdmain)
{
	uint32_t y = 0;
	uint32_t u = 0;
	uint32_t v = 0;
#if 0
	if(isdmain) {
		//cur buf
		y = info->cur_buf.y_paddr;
		u = info->cur_buf.uv_paddr;
		ncu_set_cur_buffer(y, u);
	}
#endif
	//ref0 buf
	y = info->ref_buf0.y_paddr;
	u = info->ref_buf0.uv_paddr;
	ncu_set_ref0_buffer(y, u);
	//ref1 buf
	y = info->ref_buf0.y_paddr;
	u = info->ref_buf0.uv_paddr;
	//ncu_set_ref0_buffer(y, u);
	//y = info->ref_buf1.y_paddr;
	//u = info->ref_buf1.uv_paddr;
	ncu_set_ref1_buffer(y, u);
	//sta
	ncu_reg_write(YUV_STA_FRM_MAX_NUM, info->sta_buf.cnt-1);
	ncu_reg_write(Y_STA_FRM_STRIDE, info->sta_buf.ysize);
	y = info->sta_buf.y_paddr;
	u = info->sta_buf.u_paddr;
	v = info->sta_buf.v_paddr;
	ncu_set_sta_buffer(y, u, v);
	//do not use psn
#if 0
	//psn
	y = info->psn_buf.y_paddr;
	u = info->psn_buf.u_paddr;
	v = info->psn_buf.v_paddr;
	ncu_set_psn_buffer(y, u, v);
#endif

	return 0;
}

int ncu_config(ncu_opt *opt)
{
	uint32_t sta_y_stride;
	uint32_t sta_uv_stride;
	ncu_info *pncuinfo;

    pncuinfo = (ncu_info*)ncu_get_info();

	sta_y_stride = DIV_ROUND_UP(opt->frm_w, 28);
	sta_uv_stride = DIV_ROUND_UP(opt->frm_w, 16);

	pncuinfo->sta_attr.sta_y_stride = ALLIGN(sta_y_stride, 16);
	pncuinfo->sta_attr.sta_uv_stride = ALLIGN(sta_uv_stride, 16);

    ncu_set_frame_size(opt->frm_w, opt->frm_h);
    //ncu_set_src_dst_stride(opt->frm_w);
	pncuinfo->psn_attr.psn_y_stride = ALLIGN(opt->frm_w/2, 16);
	pncuinfo->psn_attr.psn_uv_stride = ALLIGN(opt->frm_w/4, 16);
	ncu_set_psn_stride(pncuinfo->psn_attr.psn_y_stride, pncuinfo->psn_attr.psn_uv_stride);
    ncu_set_sta_stride(pncuinfo->sta_attr.sta_y_stride, pncuinfo->sta_attr.sta_uv_stride, pncuinfo->sta_attr.sta_uv_stride);

    //ncu_reg_write(NCU_SREG_CNTRL,0x1);
    ncu_fun_ctrl(opt->funcs);
    //ncu_in_mode(opt->dmain);
    //ncu_out_mode(opt->dmaout);
    //ncu_first_frame();

	return 0;
}
